﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using Newtonsoft.Json;
using RFS.BizLogic.utils;
using Formatting = Newtonsoft.Json.Formatting;

namespace ycx
{
    public static class Utils
    {
        static SnowflakeIdGenerator s = new SnowflakeIdGenerator();

        public static ulong NewSnowflakeId(this object o)
        {
            return s.NextId();
        }

        public static Stream ToStream(this string inputString)
        {
            MemoryStream stream = new MemoryStream();
            StreamWriter writer = new StreamWriter(stream);
            writer.Write(inputString);
            writer.Flush();
            stream.Position = 0;
            return stream;
        }

        public static string ToStringFromStream(this Stream stream)
        {
            StreamReader reader = new StreamReader(stream);
            return reader.ReadToEnd();
        }

        public static string ToStringBase64FromStream(this MemoryStream stream)
        {
            var ss = stream.ToArray();
            string s2 = Convert.ToBase64String(ss);
            return s2;
        }

        public static MemoryStream ToMemoStreamFromBase64(this string s)
        {
            // 将 Base64 字符串转换回 byte 数组
            byte[] byteArray = Convert.FromBase64String(s);
            // 使用 MemoryStream 来读取 byte 数组
            MemoryStream stream = new MemoryStream(byteArray);
            // 确保流的位置在开始处
            stream.Position = 0;
            return stream;
        }

        public static string ToDateISO(this DateTime o)
        {
            return $"{o:yyyy-MM-dd}";
        }


        public static void ToClipboard(this string o)
        {
            // 1.UseUIThread(() =>
            // {
            Clipboard.Clear();
            Clipboard.SetDataObject(o);
            Clipboard.Flush();

            // });
        }


        static ConcurrentDictionary<string, CancellationTokenSource> _tasks =
            new ConcurrentDictionary<string, CancellationTokenSource>();

        public static void DebounceExecute(this object o, Action action, int milliseconds = 300, string id = null)
        {
            lock (_tasks)
            {
                CancellationTokenSource cs = null;

                var key = string.IsNullOrEmpty(id) ? action.GetHashCode().ToString() : id;
                // key.Echo();
                if (_tasks.ContainsKey(key))
                {
                    _tasks.TryRemove(key, out cs);
                    cs?.Cancel();
                }

                // else
                // {
                cs = new CancellationTokenSource();
                _tasks[key] = cs;
                // }

                Task.Delay(milliseconds, cs.Token)
                    .ContinueWith(t =>
                    {
                        if (!t.IsCanceled)
                        {
                            action?.Invoke();
                        }
                    }, cs.Token);
            }
        }

        //  
        // static private readonly Action<string> _debouncedAction;
        //
        //  public static void  ExampleUsage()
        //  {
        //      // Wrap the method you want to debounce
        //      _debouncedAction = Debounce<string>(ExecuteAction, 300);
        //  }
        //
        //  public static void CallFunction(string input)
        //  {
        //      // Call this method rapidly; only the last call will be invoked after the specified delay
        //      _debouncedAction(input);
        //  }
        //
        //  private static void ExecuteAction(string data)
        //  {
        //      // This will only be invoked for the last call
        //      Console.WriteLine($"Executing action with data: {data}");
        //  }
        //  

        public static void MakeSurePathIsAvaliable(this string filePath)
        {
            var p = Path.GetDirectoryName(filePath);
            if (string.IsNullOrEmpty(p)) return;
            // string filePath = "C:\\path\\to\\file.txt";
            if (!Directory.Exists(p))
            {
                Directory.CreateDirectory(p);
            }
        }

        public static void Echo(this object o, string prefix = "", bool formated = true, bool asjson = true)
        {
            // if (string.IsNullOrEmpty(prefix) ) prefix = o.GetType().Name;
            if (asjson)
                Console.WriteLine($"###{prefix}: {o.ToJson(formated)}");
            else
            {
                Console.WriteLine($"###{prefix}: {o}");
            }
        }

        public static void TryRun(this object o, Action act)
        {
            try
            {
                act?.Invoke();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }

        public static void Report(this Stopwatch o, String prefix = "")
        {
            Console.WriteLine($"{prefix}. took time:{o.ElapsedMilliseconds} ms");
            o.Restart();
        }


        public static Stopwatch StartWatch(this object o, String prefix = "")
        {
            var st = new Stopwatch();
            Console.WriteLine($"{prefix}");
            st.Start();
            return st;
        }


        public static string ToJson(this object o, bool indented = true)
        {
            // Serialize the object to JSON
            string json = JsonConvert.SerializeObject(o, indented ? Formatting.Indented : Formatting.None);

            return json;
        }

        public static T ToObject<T>(this string o, bool indented = true)
        {
            // Serialize the object to JSON
            var obj = JsonConvert.DeserializeObject<T>(o);


            return obj;
        }

        public static string JoinToString<T>(this IEnumerable<T> o, string separator = ",")
        {
            // Serialize the object to JSON
            var obj = string.Join(separator, o);
            return obj;
        }


        public static void Required(this string o, bool pre)
        {
            if (!pre) throw new Exception(o);
        }

        //
        // public static Rectangle DetectForContent(this IImage img)
        // {
        //     var imgPath = img.Url;
        //     // Load the image containing the rectangle
        //     Bitmap image = new Bitmap(imgPath);
        //
        //     // Convert the image to a compatible pixel format (e.g., 8bpp grayscale)
        //     Bitmap compatibleImage = Grayscale.CommonAlgorithms.BT709.Apply(image);
        //
        //     // Apply edge detection filter
        //     SobelEdgeDetector edgeDetector = new SobelEdgeDetector();
        //     Bitmap edgesImage = edgeDetector.Apply(compatibleImage);
        //
        //     // Apply blob counter to find rectangles
        //     BlobCounter blobCounter = new BlobCounter();
        //     blobCounter.ProcessImage(edgesImage);
        //     Blob[] blobs = blobCounter.GetObjectsInformation();
        //
        //     if (blobs.Length < 1) throw new Exception("no blobs found");
        //
        //     var rr = blobs[0].Rectangle;
        //     foreach (Blob blob in blobs)
        //     {
        //         // Get the rectangle dimensions
        //         Rectangle rectangle = blob.Rectangle;
        //         rr = MergeRectangles(rr, rectangle);
        //     }
        //
        //     return rr;
        //
        //     Rectangle MergeRectangles(Rectangle rect1, Rectangle rect2)
        //     {
        //         int x1 = Math.Min(rect1.X, rect2.X);
        //         int y1 = Math.Min(rect1.Y, rect2.Y);
        //         int x2 = Math.Max(rect1.Right, rect2.Right);
        //         int y2 = Math.Max(rect1.Bottom, rect2.Bottom);
        //
        //         return new Rectangle(x1, y1, x2 - x1, y2 - y1);
        //     }
        // }
    }
}